package edu.stanford.bmir.protege.web.server.stkosutil.enricher.handlers;

	import com.google.common.base.Optional;

import edu.stanford.bmir.protege.web.client.dispatch.actions.CreateClassesAction;
import edu.stanford.bmir.protege.web.client.dispatch.actions.CreateClassesResult;
import edu.stanford.bmir.protege.web.client.rpc.data.EntityData;
import edu.stanford.bmir.protege.web.client.rpc.data.SubclassEntityData;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.common.UtilConstants;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.CandidateEntity;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.actions.CreateCandidateClassesAction;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.actions.CreateCandidateClassesResult;
import edu.stanford.bmir.protege.web.server.change.ChangeApplicationResult;
import edu.stanford.bmir.protege.web.server.change.ChangeDescriptionGenerator;
import edu.stanford.bmir.protege.web.server.change.CreateClassesChangeGenerator;
import edu.stanford.bmir.protege.web.server.change.FixedMessageChangeDescriptionGenerator;
import edu.stanford.bmir.protege.web.server.dispatch.AbstractHasProjectActionHandler;
import edu.stanford.bmir.protege.web.server.dispatch.ExecutionContext;
import edu.stanford.bmir.protege.web.server.dispatch.RequestContext;
import edu.stanford.bmir.protege.web.server.dispatch.RequestValidator;
import edu.stanford.bmir.protege.web.server.dispatch.validators.UserHasProjectReadPermissionValidator;
import edu.stanford.bmir.protege.web.server.msg.OWLMessageFormatter;
import edu.stanford.bmir.protege.web.server.owlapi.OWLAPIProject;
import edu.stanford.bmir.protege.web.server.owlapi.OWLAPIProjectManager;
import edu.stanford.bmir.protege.web.server.owlapi.RenderingManager;
import edu.stanford.bmir.protege.web.server.stkosutil.enricher.CandidateClassHolder;
import edu.stanford.bmir.protege.web.server.stkosutil.enricher.CandidateClassesChangeGenerator;
import edu.stanford.bmir.protege.web.shared.BrowserTextMap;
import edu.stanford.bmir.protege.web.shared.ObjectPath;
import edu.stanford.bmir.protege.web.shared.project.ProjectId;
import edu.stanford.bmir.protege.web.shared.user.UserId;

import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.EntityType;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLOntologyChange;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;

	/**
	 * Author: Matthew Horridge<br>
	 * Stanford University<br>
	 * Bio-Medical Informatics Research Group<br>
	 * Date: 22/02/2013
	 */
	public class CreateCandidateClassesActionHandler{

	  
		 private OWLAPIProject getProject(String projectName) {
		        if (projectName == null) {
		            throw new NullPointerException("projectName must not be null");
		        }
		        ProjectId projectId = ProjectId.get(projectName);
		        // TODO: Log
		        return getProject(projectId);
		 }

		    /**
		     * Gets the OWLAPIProject for a given {@link ProjectId}.If a project with the specified id exists then that project
		     * will be returned, otherwise, a fresh project will be created and that fresh project returned.
		     * @param projectId The id of the project.
		     * @return The OWL API project. Not <code>null</code>.
		     */
		 private OWLAPIProject getProject(ProjectId projectId) {
		        OWLAPIProjectManager pm = OWLAPIProjectManager.getProjectManager();
		        return pm.getProject(projectId);
		 }
	   
	     public CreateCandidateClassesResult execute(String projectName, CreateCandidateClassesAction action,UserId userId) {
	    	String parentName = action.getParentName();
	    	CreateCandidateClassesResult result = new CreateCandidateClassesResult();
	    	ArrayList<SubclassEntityData> subClassEntityDataList = new ArrayList<SubclassEntityData>();
	    	result.setSubClassEntityDataList(subClassEntityDataList);
	    	OWLAPIProject project = this.getProject(projectName);
	    	RenderingManager rm = project.getRenderingManager();
	 	    OWLClass parentClass= rm.getEntity(parentName, EntityType.CLASS);
	 	    
	 	     
	    	//Set<List<OWLClass>> paths = project.getClassHierarchyProvider().getPathsToRoot(parentClass);
	        //if(paths.isEmpty()) {
	        //    throw new IllegalStateException("Class does not exist in hierarchy: " + project.getRenderingManager().getBrowserText(action.getSuperClass()));
	        //}
	        //ObjectPath<OWLClass> pathToRoot = new ObjectPath<OWLClass>(paths.iterator().next());
	 	    
	 	    ArrayList<CandidateClassHolder> alCandidateClassHolders = new ArrayList<CandidateClassHolder>();
	 	    CandidateClassHolder candidateClassHolder = new CandidateClassHolder();
	 	    candidateClassHolder.setOwlClass(parentClass);
	 	    candidateClassHolder.setCandidateChildClassList((ArrayList<CandidateEntity>)action.getCandidateEntities());
	 	    alCandidateClassHolders.add(candidateClassHolder);
	 	    CandidateClassesChangeGenerator changeGenerator = new CandidateClassesChangeGenerator(alCandidateClassHolders);
	 		ChangeDescriptionGenerator descriptionGenerator = new FixedMessageChangeDescriptionGenerator("本体丰富");
	 		ChangeApplicationResult result2 =  project.applyChanges(userId, changeGenerator, descriptionGenerator);
	 		//RenameMap renameMap = result2.getRenameMap();
	 		HashMap<OWLClass, String> hFreshClassList = changeGenerator.getFresshClassList();
	 		OWLDataFactory df = project.getDataFactory();
	 		List<OWLOntologyChange> changeList = new ArrayList<OWLOntologyChange>();
	 		ArrayList<OWLEntity> alRenamedClassList = new ArrayList<OWLEntity>();
	 		for (Entry<OWLClass, String> entry : hFreshClassList.entrySet()) {
	 			OWLClass freshClass = entry.getKey();
	 			String from = entry.getValue();
	 			OWLEntity renamedClass = result2.getRenamedEntity(freshClass);
	 			String annotaionValue= UtilConstants.FLAG_ENRICHED + ": Y" + "; " + UtilConstants.FLAG_FROM + ": " + from;
	 			OWLAnnotation commentAnno = df.getOWLAnnotation(
	 					 df.getRDFSComment(),
	 					 df.getOWLLiteral(annotaionValue, "en"));
	 			
	 			OWLAxiom ax = df.getOWLAnnotationAssertionAxiom(renamedClass.getIRI(), commentAnno);
	 			AddAxiom addAxiom =  new AddAxiom(project.getRootOntology(), ax);	 
	 			changeList.add(addAxiom);
	 			alRenamedClassList.add(renamedClass);
	 		}
	 		project.applyChanges(userId, changeList, "添加annotaion");
	 		for (OWLEntity renamedClass: alRenamedClassList){
	 			String browserText = rm.getBrowserText(renamedClass);
                String name = renamedClass.getIRI().toString();
                SubclassEntityData subEntityData = new SubclassEntityData(name, browserText, Collections.<EntityData>emptySet(), 0);
                subClassEntityDataList.add(subEntityData);
	 		} 
	 		 
	        return result;
	    }

	   
	}
